using System;

using System.ComponentModel;

using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

[assembly: WebResource("SBPweb.Controls.Web.Resources.valuepicker.js", "text/javascript")]
namespace SBPweb.Controls.Web
{
	//TODO: Optimization

	/// <summary>
	/// This class is an extension of the TextBox control. It has two button left, and two button right to the 
	/// TextBox (Decrease By 1, Decrease By 10, Increase By 1, Increase By 10) to help modify the value in it.
	/// Minimum and Maximum allowed value can be set. It also includes both client (Javascript) and
	/// server side validation. In case of invalid value postback or set at server side, an ArgumentException
	/// is thrown.
	/// </summary>
	[ToolboxData("<{0}:ValuePicker runat=server></{0}:ValuePicker>")]
	[Description("Extension of the TextBox control")]
	public class ValuePicker : WebControl
	{

		#region Private Members

		private HtmlTableCell tdDecrase10;
		private HtmlTableCell tdDecrase1;
		private HtmlTableCell tdIncrase10;
		private HtmlTableCell tdIncrase1;
		private TextBox tbValue = new TextBox();

		#endregion


		#region Properties

		/// <summary>
		/// Gets the enclosed TextBox Control.
		/// </summary>
		[Category("Behavior")]
		[Description("Access to the Textbox component of this value picker")]
		public TextBox ValueTextBox
		{
			get
			{
				return tbValue;
			}
		}

		/// <summary>
		/// Gets or sets the value of the TextBox (Also can be accessed through ValueTextBox.Text as string value)
		/// </summary>
		[Bindable(true)]
		[Category("Behavior")]
		[DefaultValue("0")]
		[Description("Gets or sets the value of this ValuePicker")]
		public int Value
		{
			get
			{
				return Convert.ToInt32(tbValue.Text);
			}
			set
			{
				tbValue.Text = value.ToString();
			}
		}

		/// <summary>
		/// Gets or sets the Minimum allowed value for this ValuePicker control
		/// </summary>
		[Bindable(true)]
		[Category("Behavior")]
		[DefaultValue("0")]
		[Description("Minimum allowed value")]
		public int MinValue
		{
			get
			{
				if (ViewState["_MinValue_"] == null)
				{
					ViewState["_MinValue_"] = 0;
				}
				return (int)ViewState["_MinValue_"];
			}
			set
			{
				ViewState["_MinValue_"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the Maximum allowed value for this ValuePicker control
		/// </summary>
		[Bindable(true)]
		[Category("Behavior")]
		[DefaultValue("999")]
		[Description("Maximum allowed value")]
		public int MaxValue
		{
			get
			{
				if (ViewState["_MaxValue_"] == null)
				{
					ViewState["_MaxValue_"] = 999;
				}
				return (int)ViewState["_MaxValue_"];
			}
			set
			{
				ViewState["_MaxValue_"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the text for the Control 'Decrease By 1'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("-1")]
		[Description("'Decrease By 1' Control's Text (TD)")]
		public string DecreaseBy1Text
		{
			get
			{
				if (ViewState["DecreaseBy1Text"] == null)
				{
					ViewState["DecreaseBy1Text"] = "-1";
				}
				return (string)ViewState["DecreaseBy1Text"];
			}
			set
			{
				ViewState["DecreaseBy1Text"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the text for the Control 'Decrease By 10'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("-10")]
		[Description("'Decrease By 10' Control's Text (TD)")]
		public string DecreaseBy10Text
		{
			get
			{
				if (ViewState["DecreaseBy10Text"] == null)
				{
					ViewState["DecreaseBy10Text"] = "-10";
				}
				return (string)ViewState["DecreaseBy10Text"];
			}
			set
			{
				ViewState["DecreaseBy10Text"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the text for the Control 'Increase By 1'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("+1")]
		[Description("'Increase By 1' Control's Text (TD)")]
		public string IncreaseBy1Text
		{
			get
			{
				if (ViewState["IncreaseBy1Text"] == null)
				{
					ViewState["IncreaseBy1Text"] = "+1";
				}
				return (string)ViewState["IncreaseBy1Text"];
			}
			set
			{
				ViewState["IncreaseBy1Text"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the text for the Control 'Increase By 10'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("+10")]
		[Description("'Increase By 10' Control's Text (TD)")]
		public string IncreaseBy10Text
		{
			get
			{
				if (ViewState["IncreaseBy10Text"] == null)
				{
					ViewState["IncreaseBy10Text"] = "+10";
				}
				return (string)ViewState["IncreaseBy10Text"];
			}
			set
			{
				ViewState["IncreaseBy10Text"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the css class for the Control 'Decrease By 1'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[Description("CssClass for 'Decrease By 1' TD element")]
		public string DecreaseBy1CssClass
		{
			get
			{
				String s = (String)ViewState["DecreaseBy1CssClass"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["DecreaseBy1CssClass"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the css class for the Control 'Decrease By 10'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[Description("CssClass for 'Decrease By 10' TD element")]
		public string DecreaseBy10CssClass
		{
			get
			{
				String s = (String)ViewState["DecreaseBy10CssClass"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["DecreaseBy10CssClass"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the css class for the Control 'Increase By 1'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[Description("CssClass for 'Increase By 1' TD element")]
		public string IncreaseBy1CssClass
		{
			get
			{
				String s = (String)ViewState["IncreaseBy1CssClass"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["IncreaseBy1CssClass"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the css class for the Control 'Increase By 10'
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[Description("CssClass for 'Increase By 10' TD element")]
		public string IncreaseBy10CssClass
		{
			get
			{
				String s = (String)ViewState["IncreaseBy10CssClass"];
				return ((s == null) ? String.Empty : s);
			}
			set
			{
				ViewState["IncreaseBy10CssClass"] = value;
			}
		}

		#endregion


		#region Overrided Members
		/// <summary>
		/// Render the controls, and validate the value posted back from the web UI.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			HtmlTable table = new HtmlTable();
			table.CellPadding = 0;
			table.CellSpacing = 0;
			table.Style.Add(HtmlTextWriterStyle.FontSize, "x-small");
			HtmlTableRow tr = new HtmlTableRow();
			HtmlTableCell tdTb = new HtmlTableCell();
			tdDecrase1 = new HtmlTableCell();
			tdDecrase1.InnerHtml = DecreaseBy1Text;
			tdDecrase1.Attributes.Add("class", DecreaseBy1CssClass);
			tdDecrase10 = new HtmlTableCell();
			tdDecrase10.InnerHtml = DecreaseBy10Text;
			tdDecrase10.Attributes.Add("class", DecreaseBy10CssClass);
			tdIncrase1 = new HtmlTableCell();
			tdIncrase1.InnerHtml = IncreaseBy1Text;
			tdIncrase1.Attributes.Add("class", IncreaseBy1CssClass);
			tdIncrase10 = new HtmlTableCell();
			tdIncrase10.InnerHtml = IncreaseBy10Text;
			tdIncrase10.Attributes.Add("class", IncreaseBy10CssClass);
			tdTb.Controls.Add(tbValue);
			tr.Cells.Add(tdDecrase1);
			tr.Cells.Add(tdDecrase10);
			tr.Cells.Add(tdTb);
			tr.Cells.Add(tdIncrase1);
			tr.Cells.Add(tdIncrase10);
			table.Rows.Add(tr);
			Controls.Add(table);

			if (Page.Request[tbValue.ClientID] != null)
			{
				int RequestValue = Convert.ToInt32(Page.Request[tbValue.ClientID]);
				if (RequestValue < MinValue || RequestValue > MaxValue)
				{
					throw new ArgumentException(String.Format("Invalid value given from the request! Value must be between {0} and {1}", MinValue, MaxValue));
				}
			}

			base.OnInit(e);
		}

		/// <summary>
		/// Set attributes for the controls, and register necessary script resources
		/// </summary>
		/// <param name="e"></param>
		protected override void OnPreRender(EventArgs e)
		{
			tbValue.Attributes["onblur"] = String.Format("blurMini('{0}',{1},{2},{3});", tbValue.ClientID, MinValue, MaxValue,tbValue.Text);
			tbValue.Attributes["onkeypress"] = String.Format("return KeyPressMini(event,'{0}',{1},{2});", tbValue.ClientID, MinValue, MaxValue);

			tdDecrase10.Attributes["class"] = DecreaseBy10CssClass;
			tdDecrase10.Attributes["onclick"] = String.Format("decreaseMiniBy10('{0}',{1});", tbValue.ClientID, MinValue);

			tdDecrase1.Attributes["class"] = DecreaseBy1CssClass;
			tdDecrase1.Attributes["onclick"] = String.Format("decreaseMini('{0}',{1});", tbValue.ClientID, MinValue);

			tdIncrase1.Attributes["class"] = IncreaseBy1CssClass;
			tdIncrase1.Attributes["onclick"] = String.Format("increaseMini('{0}',{1});", tbValue.ClientID, MaxValue);

			tdIncrase10.Attributes["class"] = IncreaseBy10CssClass;
			tdIncrase10.Attributes["onclick"] = String.Format("increaseMiniBy10('{0}',{1});", tbValue.ClientID, MaxValue);

			// add static js library (can be cached by browsers)
			Page.ClientScript.RegisterClientScriptInclude
			(
				"valuePickerJS",
				Page.ClientScript.GetWebResourceUrl
				(
					this.GetType(), "SBPweb.Controls.Web.Resources.valuepicker.js"
				)
			);

			base.OnPreRender(e);
		}

		/// <summary>
		/// Validate values set on server side
		/// </summary>
		/// <param name="e"></param>
		protected override void OnUnload(EventArgs e)
		{
			if (MaxValue < MinValue)
			{
				throw new ArgumentException("The Minimum value must be less or equal than the Maximum value!");
			}
			if (Value < MinValue || Value > MaxValue)
			{
				throw new ArgumentException(String.Format("Invalid value set! Value must be between {0} and {1}", MinValue, MaxValue));
			}
			base.OnUnload(e);
		}

		#endregion

	}
}
